/**
 * Android Application Data content Interface for MultipleNestingTagging Library
 */
package org.chungyan5.multiplenestingtagging.mobile;

import java.sql.SQLException;
import java.util.NoSuchElementException;

import org.chungyan5.multiplenestingtagging.DbConn;
import org.chungyan5.multiplenestingtagging.Item;
import org.chungyan5.multiplenestingtagging.mobile.DbConnImp.DbReturnDataImp;
import org.chungyan5.multiplenestingtagging.opencloud.MNTCloud;
import org.chungyan5.multiplenestingtagging.opencloud.MNTTag;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;

/**
 * @author yan
 *
 * CONTENT_URI/Tag: _id, TagName
 * CONTENT_URI/Item: _id, ItemName
 * 
 */
public class MNTContentProvider extends ContentProvider {

	private MNTCloud cloud;
	
	public static final String AUTHORITY = "org.chungyan5.multiplenestingtagging.mobile";
	public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
	public static final String TAGS_PATH = "tags";
	public static final String ITEMS_PATH = "items";
	public static final String ITEM_ATTACHED_TAGS_PATH = "attachedTags";
	public static final String TAG_ATTACHED_ITEMS_PATH = "attachedItems";
	public static final String TAG_ATTACHED_SEL_TAGS_PATH = "attachedSelTags";
	public static final String TAG_ATTACHED_REL_TAGS_PATH = "attachedRelTags";
	public static final String DB_PATH = "db";

	public static final String TAG_ID = DbConnImp.TABLE_TAG_COL_TAG_PTR; 
	public static final String TAG_NAME = DbConnImp.TABLE_TAG_COL_TAG_NAME; 
	public static final String ITEM_ID = DbConnImp.TABLE_ITEM_COL_ITEM_PTR; 
	public static final String ITEM_NAME = DbConnImp.TABLE_TAG_COL_TAG_NAME; 

	public static final String REL_SEL_TAG_ID = "_id"; 
	public static final String REL_SEL_TAG_NAME = "TagName"; 

	private static final int TAG = 1;
	private static final int TAGS = 2;
	private static final int ITEM = 3;
	private static final int ITEMS = 4;
	private static final int ATTACHED_TAGS = 5;
	private static final int ATTACHED_ITEMS = 6;
	private static final int ATTACHED_SEL_TAGS = 7;
	private static final int ATTACHED_REL_TAGS = 8;
	private static final int DB = 9;

	private static final UriMatcher uriMatcher;
    static {
       uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
       uriMatcher.addURI(AUTHORITY, TAGS_PATH, TAGS);
       uriMatcher.addURI(AUTHORITY, TAGS_PATH + "/#", TAG);      
       uriMatcher.addURI(AUTHORITY, ITEMS_PATH, ITEMS);
       uriMatcher.addURI(AUTHORITY, ITEMS_PATH + "/#", ITEM);      
       uriMatcher.addURI(AUTHORITY, ITEM_ATTACHED_TAGS_PATH, ATTACHED_TAGS);
       uriMatcher.addURI(AUTHORITY, TAG_ATTACHED_ITEMS_PATH, ATTACHED_ITEMS);
       uriMatcher.addURI(AUTHORITY, TAG_ATTACHED_SEL_TAGS_PATH, ATTACHED_SEL_TAGS);
       uriMatcher.addURI(AUTHORITY, TAG_ATTACHED_REL_TAGS_PATH, ATTACHED_REL_TAGS);
       uriMatcher.addURI(AUTHORITY, DB_PATH, DB);
    }

	/* (non-Javadoc)
	 * @see android.content.ContentProvider#onCreate()
	 */
	@Override
	public boolean onCreate() {
		DbConnImp dbConnImp = new DbConnImp(getContext());
		cloud = new MNTCloud(dbConnImp);							// create cloud
		return true;
	}

	public void close() {
		cloud.close();
	}
	
	/* (non-Javadoc)
	 * @see android.content.ContentProvider#getType(android.net.Uri)
	 */
	@Override
	public String getType(Uri uri) {
		switch (uriMatcher.match(uri)) {
        	case TAG:							//---get a particular tag---
        		return "vnd.android.cursor.item/vnd.chungyan5.tags";
        	case TAGS:                			//---get all tags---
        		return "vnd.android.cursor.dir/vnd.chungyan5.tags";
        	case ITEM:
        		return "vnd.android.cursor.item/vnd.chungyan5.items";
        	case ITEMS:                
        		return "vnd.android.cursor.dir/vnd.chungyan5.items";
        	case ATTACHED_TAGS:                
        		return "vnd.android.cursor.dir/vnd.chungyan5.attachedTags";
        	case ATTACHED_ITEMS:                
        		return "vnd.android.cursor.dir/vnd.chungyan5.attachedItems";
        	case DB:                
        		return "vnd.android.cursor.item/vnd.chungyan5.db";
        	default:
        		throw new IllegalArgumentException("Unsupported URI: " + uri);        
		}
	}

	/* (non-Javadoc)
	 * @see android.content.ContentProvider#insert(android.net.Uri, android.content.ContentValues)
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		switch (uriMatcher.match(uri)) {
			case TAGS :										// create tags
				try {
					MNTTag mntTag = new MNTTag();
					mntTag.createNew(values.getAsString(DbConn.TABLE_TAG_COL_TAG_NAME));
					uri = Uri.withAppendedPath(uri, "/" + Long.toString(mntTag.getTagPointer()));
					getContext().getContentResolver().notifyChange(uri, null);
				} catch (SQLException e) {
					e.printStackTrace();
				}		
				break;
        	case ITEMS:                
        		try {
					Item mntItem = new Item();
					mntItem.createNew(values.getAsString(DbConn.TABLE_ITEM_COL_ITEM_NAME));
					uri = Uri.withAppendedPath(uri, "/" + Long.toString(mntItem.getItemPointer()));
					getContext().getContentResolver().notifyChange(uri, null);
				} catch (SQLException e) {
					e.printStackTrace();
				}
				break;
        	case ATTACHED_TAGS:
    			try {
					Item mntItem = new Item();
					long id = mntItem.addTag(values.getAsLong(DbConn.TABLE_TAGS_ITEMS_COL_ITEM_PTRS), values.getAsLong(DbConn.TABLE_TAGS_ITEMS_COL_TAG_PTRS));
					uri = Uri.withAppendedPath(uri, "/" + id);
					getContext().getContentResolver().notifyChange(uri, null);
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
				break;
			default :
        		throw new IllegalArgumentException("Unsupported URI: " + uri);        
		}
		return uri;
	}

	/* 
	 * List of URLs for corresponding parameters and return 
	 * <ul>
	 * <li> 1) content://org.chungyan5.multiplenestingtagging.mobile/db
	 * <li> <li> para. -- null
	 * <li> <li> return a table in "Result" which row as "0" or "-1"  
	 * </ul>
	 * 
	 * (non-Javadoc)
	 * @see android.content.ContentProvider#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String)
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		DbConnImp.DbReturnDataImp dbReturnData;
		Cursor returnCursor = null;
		switch (uriMatcher.match(uri)) {
			case TAGS :
				dbReturnData = (DbReturnDataImp) MNTTag.listTags(projection, selection);
				break;
        	case ITEMS:                
				dbReturnData = (DbReturnDataImp) Item.listItems(projection, selection);
				break;
        	case ATTACHED_TAGS:
        		Item item = new Item();
        		dbReturnData = (DbReturnDataImp) item.listAllTagsWithAttachedIndication(Long.parseLong(selection));
				break;
        	case ATTACHED_ITEMS:
        		MNTTag mnttag = new MNTTag();
        		dbReturnData = (DbReturnDataImp) mnttag.listAttachedItems(Long.parseLong(selection), cloud);
				break;
        	case ATTACHED_SEL_TAGS:					// must be query after TAG_ATTACHED_ITEMS_PATH
        		dbReturnData = (DbReturnDataImp) cloud.getTableSelectTag();
				break;
        	case ATTACHED_REL_TAGS:					// must be query after TAG_ATTACHED_ITEMS_PATH
        		dbReturnData = (DbReturnDataImp) cloud.getTableRelatedTag();
				break;
        	case DB:
        		MatrixCursor matrixCursor = new MatrixCursor(new String[] {"Result"});
        		if (MNTCloud.dbConn.export()) matrixCursor.addRow(new Object[] {0});
        		else matrixCursor.addRow(new Object[] {-1});
        		dbReturnData = new DbReturnDataImp(matrixCursor);
				break;
			default :
	    		throw new IllegalArgumentException("Unsupported URI: " + uri);        
		}
		
		returnCursor = dbReturnData.getCursor();
		returnCursor.setNotificationUri(getContext().getContentResolver(), uri);
		return returnCursor;
	}

	/* Update Tag and Item for its name only, Id always be consist. 
	 * <p>
	 * List of URLs for corresponding parameters and return 
	 * <ul>
	 * <li> 1) content://org.chungyan5.multiplenestingtagging.mobile/db
	 * <li> <li> para. -- null
	 * <li> <li> return -1 -- err, 0 -- completed 
	 * </ul>
	 * 
	 * (non-Javadoc)
	 * @see android.content.ContentProvider#update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[])
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		int retInt;
		switch (uriMatcher.match(uri)) {
			case TAGS :
				MNTTag mntTag = new MNTTag();
				mntTag.changeName(values.getAsString(DbConn.TABLE_TAG_COL_TAG_NAME)
						, values.getAsLong(DbConn.TABLE_TAG_COL_TAG_PTR));
				uri = Uri.withAppendedPath(uri, "/" + Long.toString(mntTag.getTagPointer()));
				getContext().getContentResolver().notifyChange(uri, null);
				retInt = 0;
				break;
	    	case ITEMS:                
				Item mntItem = new Item();
				mntItem.changeName(values.getAsString(DbConn.TABLE_ITEM_COL_ITEM_NAME)
						, values.getAsLong(DbConn.TABLE_ITEM_COL_ITEM_PTR));
				uri = Uri.withAppendedPath(uri, "/" + Long.toString(mntItem.getItemPointer()));
				getContext().getContentResolver().notifyChange(uri, null);
				retInt = 0;
				break;
        	case DB:
        		if (MNTCloud.dbConn.retore()) retInt = 0;
        		else retInt = -1;
				break;
			default :
	    		throw new IllegalArgumentException("Unsupported URI: " + uri);        
		}
		return retInt;
	}

	/*  
	 *  (non-Javadoc)
	 * @see android.content.ContentProvider#delete(android.net.Uri, java.lang.String, java.lang.String[])
	 * 
	 * @param selection as the name of tag / Item only 
	 * 
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		int returnCnt = 0;
		switch (uriMatcher.match(uri)) {
			case TAGS :
				MNTTag mntTag = new MNTTag();
				returnCnt = mntTag.remove(selection);
				break;
	    	case ITEMS:     
	    		{
				Item mntItem = new Item();
				returnCnt = mntItem.remove(selection);
	    		}
				break;
        	case ATTACHED_TAGS:
        		{
				Item mntItem = new Item();
				// assume the input selection String as "itemPtr,tagPtr"
				String[] itemTagPtrs = selection.split(",");
				returnCnt = mntItem.removeTag(Long.parseLong(itemTagPtrs[0]), Long.parseLong(itemTagPtrs[1]));
        		}
				break;
			// @param selection - null will remove all, a positive integer indicates how many to remove fr. top of Selected Tag set
        	case ATTACHED_SEL_TAGS:
        		if (selection==null) {
            		returnCnt = cloud.getSizeSelectTag();
            		cloud.clrSelectTags();
        		} else {
        			int i;
        			for (i=0;i<Integer.parseInt(selection);i++) {
            			try {
            				cloud.popSelectTag();
            			} catch (NoSuchElementException nsee) {
            				// nothing to do when empty already of this set
            				break;
            			}
        			}
        			returnCnt = i;
        		}
				break;
        	case ATTACHED_REL_TAGS:
        		returnCnt = cloud.getSizeRelatedTag();
        		cloud.clrRelatedTags();
				break;
			default :
	    		throw new IllegalArgumentException("Unsupported URI: " + uri);        
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return returnCnt;
	}

}
